﻿using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;

namespace Devonline.AspNetCore;

public static class QueryableExtensions
{
    /// <summary>
    /// 返回 IQueryable 的条件 Where 查询
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="queryable"></param>
    /// <param name="condition"></param>
    /// <param name="predicate"></param>
    /// <returns></returns>
    public static IQueryable<T> WhereIf<T>(this IQueryable<T> queryable, bool condition, Expression<Func<T, bool>> predicate) => condition ? queryable.Where(predicate) : queryable;

    /// <summary>
    /// 返回分页查询的结果
    /// OrderBy 表达式支持 a; a, b; a, b desc; 等写法, 因此不需要在做具体解析处理
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="queryable"></param>
    /// <param name="pagedRequest"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static async Task<PagedResult<T>> PageByAsync<T>(this IQueryable<T> queryable, PagedRequest pagedRequest)
    {
        if (!string.IsNullOrWhiteSpace(pagedRequest.Orderby))
        {
            queryable = queryable.OrderBy(pagedRequest.Orderby);
        }

        var result = new PagedResult<T>
        {
            PageIndex = pagedRequest.PageIndex,
            PageSize = pagedRequest.PageSize,
            Total = await queryable.CountAsync()
        };

        queryable = queryable.Skip((pagedRequest.PageIndex - 1) * pagedRequest.PageSize).Take(pagedRequest.PageSize);
        result.Data = await queryable.ToListAsync();

        return result;
    }
    /// <summary>
    /// 返回分页查询的结果
    /// OrderBy 表达式支持 a; a, b; a, b desc; 等写法, 因此不需要在做具体解析处理
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="queryable"></param>
    /// <param name="queryOptions"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static async Task<PagedResult<T>> PageByAsync<T>(this IQueryable<T> queryable, QueryOptions<T> queryOptions)
    {
        queryOptions.Skip ??= UNIT_ZERO;
        queryOptions.Top ??= DEFAULT_PAGE_SIZE;
        if (queryOptions.Orderby is not null)
        {
            queryable = queryable.OrderBy(queryOptions.Orderby.ToString());
        }

        var result = new PagedResult<T>
        {
            PageIndex = (queryOptions.Skip.Value / queryOptions.Top.Value) + 1,
            PageSize = queryOptions.Top.Value,
            Total = await queryable.CountAsync()
        };

        queryable = queryable.Skip(queryOptions.Skip.Value).Take(queryOptions.Top.Value);
        result.Data = await queryable.ToListAsync();

        return result;
    }
}